package nqueens.algorithm;

/**
Algorithm to generate row numbers for placing n>3 queens in consecutive columns of an n×n board.

Compute the remainder r of division n by 6.
Case 1 (r is neither 2 nor 3): Write a list of the consecutive even numbers from 2 to n inclusive and append
to it the consecutive odd numbers from 1 to n inclusive.
Case 2 (r is 2): Write a list of the consecutive odd numbers from 1 to n inclusive and then swap the first and
penultimate numbers.  Append to the list the consecutive even numbers from 2 to n inclusive and then swap number 4
and the last number in the expanded list.
Case 3 (r is 3) Apply the directives of Case 2 to n-1 instead of n and append n to the created list.
 */
public class DrLevitin extends Algorithm {

    public DrLevitin(boolean validateSolutions) {
        super(validateSolutions);
    }

    @Override
    protected void solve(int n) throws InterruptedException {
        int[] list = new int[n];
        int r;
        int middle;
        r = (n % 6);

        //case 1
        if (r != 2 && r != 3) {
            int y = 2;
            // if it's an even number, the middle is exactly half
            if (n % 2 == 0) {
                middle = (n / 2);
            } // if it's an odd number, the middle needs to be rounded up
            else {
                middle = (n / 2);
            }

            for (int x = 0; x < middle; x++) {
                // fill with even
                list[x] = y;
                y = y + 2;
            }
            y = 1;
            for (int x = middle; x < n; x++) {
                // fill with odd
                list[x] = y;
                y = y + 2;
            }

            for (int a = 0; a < n; a++) {
            }

        } else {
            //case 2
            if (r == 2) {
                int y = 1;
                int temp = 0;

                //fill with odd starting with 1
                for (int x = 0; x < (n / 2); x++) {
                    list[x] = y;
                    y = y + 2;
                }
                //append
                temp = list[0];
                list[0] = list[(n / 2) - 2];
                list[(n / 2) - 2] = temp;

                y = 2;
                //fill with even
                for (int x = (n / 2); x < list.length; x++) {
                    list[x] = y;
                    y = y + 2;
                }
                //re-swap number 4 and the last number
                for (int s = 0; s < n; s++) {
                    if (list[s] == 4) {
                        temp = list[s];
                        list[s] = list[n - 1];
                        list[n - 1] = temp;
                    }
                }


                for (int a = 0; a < n; a++) {
                }

            } else {
                //case 3
                if (r == 3) {
                    int y = 1;
                    int temp = 0;
                    int curN = n;
                    n = n - 1;

                    //fill with odd starting with 1
                    for (int x = 0; x < (n / 2); x++) {
                        list[x] = y;
                        y = y + 2;
                    }
                    //append
                    temp = list[0];
                    list[0] = list[(n / 2) - 2];
                    list[(n / 2) - 2] = temp;

                    y = 2;
                    //fill with even
                    for (int x = (n / 2); x < list.length; x++) {
                        list[x] = y;
                        y = y + 2;
                    }
                    //re-swap number 4 and the last number
                    for (int s = 0; s < n; s++) {
                        if (list[s] == 4) {
                            temp = list[s];
                            list[s] = list[n - 1];
                            list[n - 1] = temp;
                        }
                    }

                    // assign (n-1) to equal the original N
                    list[n] = curN;

                    // return N back to its normal number to prevent infinite loop
                    n = curN;

                    for (int a = 0; a < n; a++) {
                    }

                }

            }
        }

        // fix for printing purposes
        for (int t = 0; t < list.length; t++) {
            list[t] = list[t] - 1;
        }
        setChessBoard(convertToChessBoard(list));
        validateSolution();
        setLastSolutionSolved(convertToChessBoard(list));
    }
}

